#include "aky_program/aky_com_include.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
/* #include <string.h> */
#include <stdint.h>    //  Added by RKW, needed for types uint8_t, uint32_t; requires C99 compiler
/******************************************************************************
 * SHA-256.
 */
void sha256_initialize(sha256 *sha) 
{
    int i;
    for (i = 0; i < 17; ++i) sha->buffer[i] = 0;
    sha->state[0] = 0x6a09e667;
    sha->state[1] = 0xbb67ae85;
    sha->state[2] = 0x3c6ef372;
    sha->state[3] = 0xa54ff53a;
    sha->state[4] = 0x510e527f;
    sha->state[5] = 0x9b05688c;
    sha->state[6] = 0x1f83d9ab;
    sha->state[7] = 0x5be0cd19;
    for (i = 0; i < 8; ++i) sha->length[i] = 0;
}

//  Changed by RKW, formal args are now const uint8_t, uint_32
//    from const unsigned char, unsigned long respectively
//由RKW更改，形式参数现在是const uint8_t，uint_32
//分别从const unsigned char、unsigned long开始
void sha256_update(sha256 *sha,
                   const uint8_t *message,
                   uint32_t length) 
{
    int i, j;
    /* Add the length of the received message, counted in
     * bytes, to the total length of the messages hashed to
     * date, counted in bits and stored in 8 separate bytes. */
	/*添加接收到的消息的长度，以计
	*字节数，等于散列到的消息的总长度
	*日期，以比特计数并存储在8个单独的字节中*/	 
    for (i = 7; i >= 0; --i) 
	{
        int bits;
        if (i == 7)
            bits = length << 3;
        else if (i == 0 || i == 1 || i == 2)
            bits = 0;
        else
            bits = length >> (53 - 8 * i);
        bits &= 0xff;
        if (sha->length[i] + bits > 0xff) 
		{
            for (j = i - 1; j >= 0 && sha->length[j]++ == 0xff; --j);
        }
        sha->length[i] += bits;
    }
    /* Add the received message to the SHA buffer, updating the
     * hash at each block (each time the buffer is filled). */
	/*将接收到的消息添加到SHA缓冲区，更新
	*每个块的哈希值（每次缓冲区被填满时）*/	 
    while (length > 0) 
	{
        /* Find the index in the SHA buffer at which to
         * append what's left of the received message. */
		/*在SHA缓冲区中查找索引
		*附加接收到的消息的剩余部分*/		 
        int index = sha->length[6] % 2 * 32 + sha->length[7] / 8;
        index = (index + 64 - length % 64) % 64;
        /* Append the received message bytes to the SHA buffer until
         * we run out of message bytes or until the buffer is filled. */
		/*将接收到的消息字节附加到SHA缓冲区，直到
		*我们用完了消息字节，或者直到缓冲区被填满*/		 
        for (;length > 0 && index < 64; ++message, ++index, --length) 
		{
            sha->buffer[index / 4] |= *message << (24 - index % 4 * 8);
        }
        /* Update the hash with the buffer contents if the buffer is full. */
		/*如果缓冲区已满，则使用缓冲区内容更新哈希*/
        if (index == 64) 
		{
            /* Update the hash with a block of message content. See FIPS 180-2
             * (<csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf>)
             * for a description of and details on the algorithm used here. */
            // Changed by RKW, const unsigned long becomes const uint32_t
			/*使用消息内容块更新哈希值。参见FIPS 180-2
			*（<csrc.nest.gov/出版物/fips/fips180-2/fips180-2.pdf>）
			*关于这里使用的算法的描述和细节*/
			//由RKW更改后，const unsigned long变为const uint32_t			
            const uint32_t k[64] = {
                0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
                0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
                0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
                0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
                0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
                0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
                0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
                0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
                0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
                0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
                0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
                0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
                0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
                0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
                0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
                0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
            };
            // Changed by RKW, unsigned long becomes uint32_t
			//由RKW更改，无符号long变为uint32_t
            uint32_t w[64], a, b, c, d, e, f, g, h;
            int t;
            for (t = 0; t < 16; ++t) 
			{
                w[t] = sha->buffer[t];
                sha->buffer[t] = 0;
            }
            for (t = 16; t < 64; ++t) 
			{
                // Changed by RKW, unsigned long becomes uint32_t
				//由RKW更改，无符号long变为uint32_t
                uint32_t s0, s1;
                s0 = (w[t - 15] >> 7 | w[t - 15] << 25);
                s0 ^= (w[t - 15] >> 18 | w[t - 15] << 14);
                s0 ^= (w[t - 15] >> 3);
                s1 = (w[t - 2] >> 17 | w[t - 2] << 15);
                s1 ^= (w[t - 2] >> 19 | w[t - 2] << 13);
                s1 ^= (w[t - 2] >> 10);
                w[t] = (s1 + w[t - 7] + s0 + w[t - 16]) & 0xffffffffU;
            }
            a = sha->state[0];
            b = sha->state[1];
            c = sha->state[2];
            d = sha->state[3];
            e = sha->state[4];
            f = sha->state[5];
            g = sha->state[6];
            h = sha->state[7];
            for (t = 0; t < 64; ++t) 
			{
                // Changed by RKW, unsigned long becomes uint32_t
				//由RKW更改，无符号long变为uint32_t
                uint32_t e0, e1, t1, t2;
                e0 = (a >> 2 | a << 30);
                e0 ^= (a >> 13 | a << 19);
                e0 ^= (a >> 22 | a << 10);
                e1 = (e >> 6 | e << 26);
                e1 ^= (e >> 11 | e << 21);
                e1 ^= (e >> 25 | e << 7);
                t1 = h + e1 + ((e & f) ^ (~e & g)) + k[t] + w[t];
                t2 = e0 + ((a & b) ^ (a & c) ^ (b & c));
                h = g;
                g = f;
                f = e;
                e = d + t1;
                d = c;
                c = b;
                b = a;
                a = t1 + t2;
            }
            sha->state[0] = (sha->state[0] + a) & 0xffffffffU;
            sha->state[1] = (sha->state[1] + b) & 0xffffffffU;
            sha->state[2] = (sha->state[2] + c) & 0xffffffffU;
            sha->state[3] = (sha->state[3] + d) & 0xffffffffU;
            sha->state[4] = (sha->state[4] + e) & 0xffffffffU;
            sha->state[5] = (sha->state[5] + f) & 0xffffffffU;
            sha->state[6] = (sha->state[6] + g) & 0xffffffffU;
            sha->state[7] = (sha->state[7] + h) & 0xffffffffU;
        }
    }
}

//  Changed by RKW, formal args are now const uint8_t, uint_32
//    from const unsigned char, unsigned long respectively
//由RKW更改，形式参数现在是const uint8_t，uint_32
//分别从const unsigned char、unsigned long开始
void sha256_finalize(sha256 *sha,
                     const uint8_t *message,
                     uint32_t length) 
{
    int i;
    // Changed by RKW, unsigned char becomes uint8_t
	//由RKW更改后，unsigned char变为uint8_t
    uint8_t terminator[64 + 8] = { 0x80 };
    /* Hash the final message bytes if necessary. */
	/*如有必要，对最终消息字节进行哈希处理*/
    if (length > 0) sha256_update(sha, message, length);
    /* Create a terminator that includes a stop bit, padding, and
     * the the total message length. See FIPS 180-2 for details. */
	/*创建一个包含停止位、填充和
	*消息的总长度。有关详细信息，请参阅FIPS 180-2*/
    length = 64 - sha->length[6] % 2 * 32 - sha->length[7] / 8;
    if (length < 9) length += 64;
    for (i = 0; i < 8; ++i) terminator[length - 8 + i] = sha->length[i];
    /* Hash the terminator to finalize the message digest. */
	/*对终止符进行哈希运算，以最终确定消息摘要*/
    sha256_update(sha, terminator, length);
    /* Extract the message digest. */
	/*提取消息摘要*/
    for (i = 0; i < 32; ++i)
	{
        sha->hash[i] = (sha->state[i / 4] >> (24 - 8 * (i % 4))) & 0xff;
    }
}

//  Changed by RKW, formal args are now uint8_t, const uint_8
//    from unsigned char, const unsigned char respectively
//由RKW更改，形式参数现在是uint8_t，const uint_8
//分别从unsigned char、const unsigned chars开始
void sha256_get(uint8_t hash[32],
                const uint8_t *message,
                int length) 
{
    int i;
    sha256 sha;
    sha256_initialize(&sha);
    sha256_finalize(&sha, message, length);
    for (i = 0; i < 32; ++i) hash[i] = sha.hash[i];
}

/******************************************************************************
 * HMAC-SHA256.
 */

typedef struct _hmac_sha256 
{
    uint8_t    digest[32];    // Changed by RKW, unsigned char becomes uint_8//由RKW更改，unsigned char变为uint_8
    uint8_t    key[64];    // Changed by RKW, unsigned char becomes uint_8//由RKW更改，unsigned char变为uint_8
    sha256    sha;
} hmac_sha256;

//  Changed by RKW, formal arg is now const uint8_t
//    from const unsigned char
//由RKW更改，形式arg现在是const uint8_t
//从const无符号字符
void hmac_sha256_initialize(hmac_sha256 *hmac,
                            const uint8_t *key, int length) 
{
    int i;
    /* Prepare the inner hash key block, hashing the key if it's too long. */
	/*准备内部哈希密钥块，如果密钥太长，则对其进行哈希处理*/
    if (length <= 64) 
	{
        for (i = 0; i < length; ++i) hmac->key[i] = key[i] ^ 0x36;
        for (; i < 64; ++i) hmac->key[i] = 0x36;
    } 
	else 
	{
        sha256_initialize(&(hmac->sha));
        sha256_finalize(&(hmac->sha), key, length);
        for (i = 0; i < 32; ++i) hmac->key[i] = hmac->sha.hash[i] ^ 0x36;
        for (; i < 64; ++i) hmac->key[i] = 0x36;
    }
    /* Initialize the inner hash with the key block. */
	/*使用键块初始化内部哈希*/
    sha256_initialize(&(hmac->sha));
    sha256_update(&(hmac->sha), hmac->key, 64);
}

//  Changed by RKW, formal arg is now const uint8_t
//    from const unsigned char
//由RKW更改，形式arg现在是const uint8_t
//从const无符号字符
void hmac_sha256_update(hmac_sha256 *hmac,
                        const uint8_t *message, int length) 
{
    /* Update the inner hash. */
	/*更新内部哈希值*/
    sha256_update(&(hmac->sha), message, length);
}

//  Changed by RKW, formal arg is now const uint8_t
//    from const unsigned char
//由RKW更改，形式arg现在是const uint8_t
//从const无符号字符
void hmac_sha256_finalize(hmac_sha256 *hmac,
                          const uint8_t *message, int length) 
{
    int i;
    /* Finalize the inner hash and store its value in the digest array. */
	/*完成内部哈希并将其值存储在摘要数组中*/
    sha256_finalize(&(hmac->sha), message, length);
    for (i = 0; i < 32; ++i) hmac->digest[i] = hmac->sha.hash[i];
    /* Convert the inner hash key block to the outer hash key block. */
	/*将内部哈希密钥块转换为外部哈希密钥块*/
    for (i = 0; i < 64; ++i) hmac->key[i] ^= (0x36 ^ 0x5c);
    /* Calculate the outer hash. */
	/*计算外部哈希值*/
    sha256_initialize(&(hmac->sha));
    sha256_update(&(hmac->sha), hmac->key, 64);
    sha256_finalize(&(hmac->sha), hmac->digest, 32);
    /* Use the outer hash value as the HMAC digest. */
	/*使用外部哈希值作为HMAC摘要*/
    for (i = 0; i < 32; ++i) hmac->digest[i] = hmac->sha.hash[i];
}

//  Changed by RKW, formal args are now uint8_t, const uint8_t
//    from unsinged char, const unsigned char respectively
//由RKW更改，形式参数现在是uint8_t，const uint8_t
//分别从无符号char、const无符号char
void hmac_sha256_get(uint8_t digest[32],
                     uint8_t *message, int message_length,
                     uint8_t *key, int key_length) 
{
    int i;
    hmac_sha256 hmac;
    hmac_sha256_initialize(&hmac, key, key_length);
    hmac_sha256_finalize(&hmac, message, message_length);
    for (i = 0; i < 32; ++i) digest[i] = hmac.digest[i];
}

/*
void sha256_get(uint8_t hash[32], const uint8_t *message, int length); // 此函数用于对消息计算摘要值，输入任意大小消息，输出32字节摘要值

void hmac_sha256_get(uint8_t digest[32], uint8_t *message, int message_length, uint8_t *key, int key_length); // 此函数用于HMAC_SHA256加密，秘钥任意长度，输出32字节

需要自己转成对应16进字字符串哦。
*/
//487031278c5577d7d00e5fe74fb72e69c8758638331e4c64c904653286bf3d98
//"666" key
//"123456abc" message



char my_char_digest[32];
char return_char_digest[128];
//deviceId + timestamp + nonce + deviceType
//deviceId+时间戳+随机数+设备类型
char Encrypted_Header_Data[100];
char Secret_Key[24]=SECRET_KEY;
// char Secret_Key[24]="vXH5ldW2htJbTAOw0TvPo6y3";
char *Encrypted_Header(char * rand_in)
{
    char Mid_Key_time[100];

    sprintf(Encrypted_Header_Data,"%s",DEVICE_ID);
    
    sprintf(Mid_Key_time,"%lld",timetostamp(g_s_mem_send.s_time));
    strcat(Encrypted_Header_Data,Mid_Key_time);
    sprintf(Mid_Key_time,"%s-cb9e-6e5f-1bc6-2057%08x",rand_in,(uint32_t)timetostamp(g_s_mem_send.s_time));
    strcat(Encrypted_Header_Data,Mid_Key_time);
    // strcat(Encrypted_Header_Data,uuid_in);
    sprintf(Mid_Key_time,DEVICE_TYPE);
    strcat(Encrypted_Header_Data,Mid_Key_time);
    // printf("%s\n", Encrypted_Header_Data);
    hmac_sha256_get((uint8_t *)my_char_digest, (uint8_t *)Encrypted_Header_Data, strlen(Encrypted_Header_Data), (uint8_t *)Secret_Key, 24);
    // printf("hmac_sha256_get result: \n");
    // for (uint16_t i = 0; i < 64; i++)
    // {
    //     printf("%c", my_char_digest[i]);
    // }
    // printf("\n");
    // for (uint16_t i = 0; i < 32; i++)
    // {
    //     printf("%02x", my_char_digest[i]);
    // }    
    // printf("\n");
    // uint16_t j = 0;
    // for (uint16_t i = 0; i < 32; i++)
    // {
    //     sprintf(&return_char_digest[j],"%02x",my_char_digest[i]);
    //     j+=2;
    // }
    volatile uint16_t i,j;
    j=0;
    for ( i = 0; i < 32; i++)
    {
       sprintf((return_char_digest + j),"%02x",(uint8_t)my_char_digest[i]);
       j+=2;
    }
    return_char_digest[32 * 2] = '\0';
    // printf("%s\r\n", return_char_digest);
    return return_char_digest;
}